/**
 * @file audio_manager.h
 * @brief 🎧 音频管理器类 - 统一管理音频的录制和播放
 * 
 * 这个类就像一个“音频指挥家”，负责协调所有音频相关的工作：
 * 
 * 🎙️ 录音功能：
 * - 管理录音缓冲区（最多10秒）
 * - 控制录音的开始/停止
 * - 跟踪录音时长
 * 
 * 🔊 播放功能：
 * - 播放本地音频文件
 * - 流式播放网络音频
 * - 缓冲区管理，避免卡顿
 * 
 * 🌐 网络功能：
 * - 接收WebSocket音频流
 * - 处理不同采样率的音频
 */

#ifndef AUDIO_MANAGER_H
#define AUDIO_MANAGER_H

#include <stdint.h>
#include <stdlib.h>
#include <string>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h"

// 🌊 流式播放状态枚举
enum StreamingState {
    STREAMING_IDLE,      // 空闲状态
    STREAMING_PLAYING,   // 正在播放
    STREAMING_PAUSED,    // 暂停状态
    STREAMING_STOPPING,  // 正在停止
    STREAMING_DOWNLOADING // 正在下载
};


class AudioManager {
public:
    /**
     * @brief 创建音频管理器
     * 
     * @param sample_rate 采样率（默认16000Hz，人声标准）
     * @param recording_duration_sec 最大录音时长（默认10秒）
     * @param response_duration_sec AI回复最大时长（默认32秒）
     */
    AudioManager(uint32_t sample_rate = 16000, 
                 uint32_t recording_duration_sec = 10,
                 uint32_t response_duration_sec = 32);
    
    /**
     * @brief 析构函数，释放所有分配的内存
     */
    ~AudioManager();

    /**
     * @brief 初始化音频管理器
     * 
     * 这个函数会分配所需的内存缓冲区。
     * 必须在使用其他功能前调用。
     * 
     * @return ESP_OK=成功，ESP_ERR_NO_MEM=内存不足
     */
    esp_err_t init();

    /**
     * @brief 反初始化，释放资源
     */
    void deinit();

    /** base64编码函数 */
    std::string base64_encode(const uint8_t*data, size_t len = 0);
    // 🎙️ ========== 录音相关功能 ==========
    
    /**
     * @brief 开始录音
     */
    void startRecording();

    /**
     * @brief 停止录音
     */
    void stopRecording();

    /**
     * @brief 查询录音状态
     * 
     * @return true=正在录音中，false=没在录音
     */
    bool isRecording() const { return is_recording; }

    /**
     * @brief 添加音频数据到录音缓冲区
     * 
     * 每次从麦克风读到数据后，用这个函数保存起来。
     * 
     * @param data 音频数据指针
     * @param samples 样本数量（注意：不是字节数！）
     * @return true=添加成功，false=缓冲区满了
     */
    bool addRecordingData(const int16_t* data, size_t samples);

    /**
     * @brief 获取录音数据
     * 
     * 用于获取已经录制的全部音频数据。
     * 
     * @param[out] length 会被设置为录音的样本数
     * @return 指向录音数据的指针
     */
    const int16_t* getRecordingBuffer(size_t& length) const;

    /**
     * @brief 清空录音缓冲区
     */
    void clearRecordingBuffer();

    /**
     * @brief 获取已录音时间
     * 
     * @return 录音时长（单位：秒）
     */
    float getRecordingDuration() const;

    /**
     * @brief 检查录音缓冲区是否已满
     * 
     * @return true 已满，false 未满
     */
    bool isRecordingBufferFull() const;

    // 🔊 ========== 音频播放相关功能 ==========

    /**
     * @brief 开始接收响应音频数据（用于WebSocket）
     */
    void startReceivingResponse();

    /**
     * @brief 添加响应音频数据块
     * 
     * @param data 音频数据
     * @param size 数据大小（字节）
     * @return true 成功，false 失败（缓冲区溢出等）
     */
    bool addResponseData(const uint8_t* data, size_t size);

    /**
     * @brief 完成响应音频接收并播放
     * 
     * @return esp_err_t 播放结果
     */
    esp_err_t finishResponseAndPlay();
    
    // 🌊 ========== 流式播放功能（边下载边播放） ==========
    
    /**
     * @brief 开始流式播放模式
     * 
     * 调用后可以不断添加音频数据块，实现边下载边播放。
     */
    void startStreamingPlayback();
    
    /**
     * @brief 添加一小段音频到播放队列
     * 
     * 在流式播放模式下，不断调用这个函数添加新的音频段。
     * 
     * @param data 音频数据
     * @param size 数据字节数
     * @return true=添加成功，false=缓冲区满
     */
    bool addStreamingAudioChunk(const uint8_t* data, size_t size);
    
    /**
     * @brief 结束流式播放
     * 
     * 播放剩余的音频数据并停止流式模式。
     */
    void finishStreamingPlayback();
    
    /**
     * @brief 检查流式播放是否正在进行
     * 
     * @return true 正在播放，false 未在播放
     */
    bool isStreamingActive() const { return streaming_state != STREAMING_IDLE; }

    /**
     * @brief 处理流式播放
     * 
     * 这个函数会在任务中调用，持续处理流式播放逻辑。
     * 
     * 注意：请在FreeRTOS任务中定期调用此函数以保持流畅播放。
     */
    void processStreamingPlayback();
    /**
     * @brief 标记流式播放已完成
     */
    void setStreamingComplete() { response_played = true; }

    /**
     * @brief 播放一段完整的音频
     * 
     * 用于播放本地存储的音频文件，一次性播放完毕。
     * 
     * @param audio_data 音频数据（PCM格式）
     * @param data_len 数据字节数
     * @param description 音频描述（如“欢迎音频”）
     * @return ESP_OK=播放成功
     */
    esp_err_t playAudio(const uint8_t* audio_data, size_t data_len, const char* description);

    /**
     * @brief 查询AI回复是否播放完成
     * 
     * @return true=已播放完成，false=还没播完
     */
    bool isResponsePlayed() const { return response_played; }

    /**
     * @brief 重置响应播放标志
     */
    void resetResponsePlayedFlag() { response_played = false; }


    // 🔧 ========== 工具函数 ==========

    /**
     * @brief 获取采样率
     * 
     * @return 采样率（Hz）
     */
    uint32_t getSampleRate() const { return sample_rate; }

    /**
     * @brief 获取录音缓冲区大小（样本数）
     * 
     * @return 缓冲区大小
     */
    size_t getRecordingBufferSize() const { return recording_buffer_size; }

    /**
     * @brief 获取响应缓冲区大小（字节）
     * 
     * @return 缓冲区大小
     */
    size_t getResponseBufferSize() const { return response_buffer_size; }
    /**
     * @brief 通过HTTP URL播放音频流
     * 
     * @param url 音频流URL
     * @param is_https 是否使用HTTPS (默认true)
     * @return esp_err_t ESP_OK表示成功
     */
    esp_err_t playHttpAudio(const char* url, bool is_https = true);

    esp_err_t playHttpAudioStream(const char* url, bool is_https);
    /**
     * @brief 停止HTTP音频流播放
     */
    void stopHttpAudio();
    // ⏱️ 流式播放超时检测相关
    uint32_t last_receive_time = 0;          // 上次数据接收时间
    TimerHandle_t timeout_timer = nullptr;   // 超时检测定时器
    bool waiting_for_data = false;          // 是否在等待数据
    static const uint32_t STREAMING_TIMEOUT_MS = 250; // 流式超时阈值
    static const uint32_t TIMER_TASK_STACK_SIZE = 4096; // 定时器任务堆栈大小
    static uint8_t silent_data[4096];      // 静态分配的静音数据缓冲区

private:
    // 🎶 音频参数
    uint32_t sample_rate;               // 采样率（Hz）
    uint32_t recording_duration_sec;    // 最大录音时长（秒）
    uint32_t response_duration_sec;     // 最大回复时长（秒）

    // 🎙️ 录音相关变量
    int16_t* recording_buffer;          // 录音数据缓冲区
    size_t recording_buffer_size;       // 缓冲区大小（样本数）
    size_t recording_length = 0;            // 已录制的样本数
    bool is_recording;                  // 是否正在录音

    // 🔊 响应音频相关变量
    int16_t* response_buffer;           // AI回复音频缓冲区
    size_t response_buffer_size;        // 缓冲区大小（字节数）
    size_t response_length;             // 已接收的样本数
    bool response_played;               // 是否已播放完成

    // 双PSRAM缓冲区
    int16_t* response_buffer1;          // 响应音频缓冲区1 (PSRAM)
    int16_t* response_buffer2;          // 响应音频缓冲区2 (PSRAM)
    size_t response_buffer1_length;     // 缓冲区1已存储数据量
    size_t response_buffer2_length;     // 缓冲区2已存储数据量
    bool current_response_buffer;       // 当前使用的缓冲区标志 (false=缓冲区1, true=缓冲区2)
    bool buffer_ready_flag;             // 缓冲区就绪标志
    static const size_t RESPONSE_BUFFER_DURATION_MS = 3000; // 3秒缓冲区时长

    // 🌊 流式播放相关变量
    StreamingState streaming_state;     // 流式播放状态
    uint8_t* streaming_buffer;          // PSRAM环形缓冲区
    uint8_t* dma_buffer;                // DMA播放缓冲区(二级缓冲)
    size_t streaming_buffer_size;       // 环形缓冲区大小
    size_t dma_buffer_size;             // DMA缓冲区大小
    volatile size_t streaming_write_pos; // 写入位置(原子访问)
    volatile size_t streaming_read_pos;  // 读取位置(原子访问)
    volatile size_t buffered_bytes;      // 已缓冲数据量(原子访问)
    uint32_t last_fill_time;            // 上次填充时间(用于流量控制)
    static const size_t STREAMING_BUFFER_SIZE = 1024 * 1024; // 1MB PSRAM环形缓冲区
    static const size_t DMA_BUFFER_SIZE = 16 * 1024;   // 16KB DMA缓冲区
    static const size_t STREAMING_CHUNK_SIZE = 16 * 1024;   // 每次处理4096字节
    //static const size_t STREAMING_TIMEOUT_MS = 5000;   // 流式超时时间(5秒)
    static const size_t MIN_BUFFERED_MS = 500;         // 最小缓冲时间(500ms)

    // 🏷️ 日志标签
    static const char* TAG;

    // 🌐 当前流式播放URL
    std::string current_streaming_url_;

    // 🎵 流式播放任务句柄
    TaskHandle_t streaming_task_handle_ = nullptr;
    

};

#endif // AUDIO_MANAGER_H